<?php

namespace app\api\service;

use app\lib\exception\TokenException;
use app\api\model\User as UserModel;
use app\lib\enum\ScopeEnum;

class UserToken extends Token{

    private $appID;    
    private $appSecret;
    private $loginUrl;

    /* 初始化微信url */
    public function __construct($code)
    {
        $this->appID = config('wx.app_id');
        $this->appSecret = config('wx.app_secret');
        $this->loginUrl = sprintf(config('wx.login_url'),$this->appID,$this->appSecret,$code);
    }

    /* 获取token主方法 */
    public function get()
    {
        $result  = curl_get($this->loginUrl);
        $wxResult = json_decode($result,true);
        if(!$wxResult){
            throw new TokenException([
                'msg' => '微信获取信息失败'
            ]);
        }else{
            if(array_key_exists('error',$wxResult)){
                /* 处理错误信息 */
                $this->processLoginError($wxResult);
            }else{
                /* 授权token */
                return $this->grantToken($wxResult);
            }
        }
    }

    /* 处理错误信息 */
    public function processLoginError($wxResult)
    {
        throw new TokenException([
            'msg' => $wxResult['errMsg'],
            'errCode' => $wxResult['errCode'],
        ]);
    }

    /* 授权token */
    public function grantToken($wxResult)
    {
        $openid = $wxResult['openid'];
        // 查询是否存在该用户
        $user = UserModel::getUserByOpenID($openid);
        if(!$user){
            $user = UserModel::create([
                'openid' => $openid,
            ]);
        }
        $uid = $user->id;
        /* 准备token数据 */
        $tokenCache = $this->prepareTokenValue($wxResult,$uid);
        /* 保存token数据 */
        return $this->saveTokenValue($tokenCache);
    }

    /* 准备token数据 */
    public function prepareTokenValue($wxResult,$uid)
    {
        $tokenCache['openid'] = $wxResult['openid'];
        $tokenCache['uid'] = $uid;
        $tokenCache['scope'] = ScopeEnum::User;
        return $tokenCache;
    }

    /* 保存token数据 */
    public function saveTokenValue($tokenCache)
    {
        $key = $this->generateToken();
        $value = json_encode($tokenCache);
        $expire_in = config('secure.expire_in');
        $result = cache($key,$value,$expire_in);
        if(!$result){
            throw new Exception();
        }
        return $key;
    }

}